package com.literature.search.core.utils;


import com.cybozu.labs.langdetect.Detector;
import com.cybozu.labs.langdetect.DetectorFactory;
import com.cybozu.labs.langdetect.LangDetectException;
import com.literature.search.core.entity.FileDocument;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: DangKong
 * @Date: 2023/3/1 15:31
 * @Description: pdf转换工具
 */

@Slf4j
public class PdfUtil {

    private PdfUtil() {
        throw new IllegalStateException("PdfUtil class error");
    }

    @Data
    @AllArgsConstructor
    static class ImageInfo{
        Integer page;
        byte[] image;
    }


    static {
        try {
            DetectorFactory.loadProfile(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("lang")).getPath());
        } catch (LangDetectException e) {
            e.printStackTrace();
        }
    }

    public static String clearText(String text) {
        text = text.replaceAll("\\t", ""); // 清除制表符
        text = text.replaceAll("\\r", ""); // 清除回车
        text = text.replaceAll("\\n", ""); // 清除换行
        // 将连续的多个空格替换为一个空格
        text = text.replaceAll("\\s{2,}", " ");
        return text;

    }

    /**
     * Get the language used in the original string.
     */
    public static String getLangUsed(String originalStr){
        String langUsed="";
        Detector detector;
        try {
            detector = DetectorFactory.create();
            detector.append(originalStr);
            langUsed= detector.detect();
        } catch (LangDetectException e) {
            e.printStackTrace();
        }
        return langUsed;
    }

    /**
     * Does the original string contain Chinese?
     */
    public static boolean containsChinese(String originalStr) {
        return "zh-cn".equals(getLangUsed(originalStr));

    }

    /**
     * Does the original string contain English?

     */
    public static boolean containsEnglish(String originalStr) {
        return "en".equals(getLangUsed(originalStr));
    }

    /**
     *PDF文件图片提取
     *
     * @param file
     * @throws Exception
     */
    public static List<ImageInfo> pdfParsePic(File file) throws Exception {
        InputStream input = null;
        List<ImageInfo> imageInfos = new ArrayList<>();
        try (PDDocument document = PDDocument.load(file)) {
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                PDPage page = document.getPage(i);
                if (null != page) {
                    //获取到所有rescourse信息
                    PDResources res = page.getResources();
                    Iterable<COSName> xit = res.getXObjectNames();
                    for (COSName cosName : xit) {
                        //System.out.println(cosName.getName());
                        //判断是否图片资源，这个提取图片也很彻底，包括页眉页脚的图片也会被获取到
                        if (res.isImageXObject(cosName)) {
                            PDImageXObject pdImageXObject = (PDImageXObject) res.getXObject(cosName);
                            BufferedImage bImage = pdImageXObject.getImage(); //获取图片
                            ByteArrayOutputStream out = new ByteArrayOutputStream(); //输出流
                            ImageIO.write(bImage, "PNG", out);
                            ImageInfo info = new ImageInfo(i + 1, out.toByteArray());
                            imageInfos.add(info);
                        }
                    }
                }
            }
            return imageInfos;
        }
    }


    /**
     * @Description // pdf 转为png

     **/
    public static void transPdf2png(String pdfPath) {
        try {
            //根据pdf文件路径取得pdf文件
            File invoiceFile = new File(pdfPath);
            // 新建pdf文件的路径
            String path = "D:\\Users\\Lenovo\\";
            PDDocument doc = PDDocument.load(invoiceFile);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                // 第二个参数是设置缩放比(即像素)
                BufferedImage image = renderer.renderImage(i, 2.5f);
                ImageIO.write(image, "PNG", new File(path + new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + ".png"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public static Map<String, Object> handlePdfText(InputStream is, FileDocument fileDocument) {
        //为pdf的每一页生成一个txt文件和一个图片文件 
        Map<String, Object> map = new HashMap<>(); // 返回的map
        ArrayList<String> textPathList = new ArrayList<>(); // 存放txt文件路径
        ArrayList<String> picPathList = new ArrayList<>(); // 存放缩略图图片文件路径
        // 提取pdf中的图片
        ArrayList<String> pngPathList = new ArrayList<>();  // 存放提取出来的png图片文件路径

        StringBuilder detectLang = new StringBuilder();
        if (is == null) {
            log.error("inputStream is null");
            throw new RuntimeException("inputStream is null"); //TODO 换成自己的异常
        }

        try (PDDocument document = PDDocument.load(is)// 加载pdf文件
        ) {
            AccessPermission ap = document.getCurrentAccessPermission(); // 获取权限
            if (!ap.canExtractContent()) {
                ap.setCanExtractContent(true);
            }

            PDFTextStripper stripper = new PDFTextStripper(); // pdf文本剥离器
            stripper.setSortByPosition(true); // 设置排序
            PDFRenderer renderer = new PDFRenderer(document); // pdf渲染器

            for (int p = 1; p <= document.getNumberOfPages(); ++p) { // 获取页数
                stripper.setStartPage(p);
                stripper.setEndPage(p);
                // 1、提取内容
                String text = stripper.getText(document);
                text = text.replaceAll("\\r", ""); // 清除回车
                text = clearText(text);
                if (p == 2) {
                    detectLang.append(text); // 检测语言
                }

                // 2、生成txt文件
                String textPath = "." + File.separator + fileDocument.getMd5() + "_" + p + ".txt";
                try (FileWriter fileWriter = new FileWriter(textPath, true) // 创建文件写入流
                ) {
                    fileWriter.write(text.trim());
                    //System.out.println(text);
                    textPathList.add(textPath);
                } catch (Exception e) {
                    log.error("解析pdf文本文件出错", e);
                    throw new RuntimeException(e); //TODO 换成自己的异常
                }

                // 3、生成图片文件
                String picPath = "." + File.separator + fileDocument.getMd5() + "_" + p + ".png";
                // 第二个参数是设置缩放比(即像素)
                BufferedImage image = renderer.renderImage(p - 1, 2.0f);
                ImageIO.write(image, "PNG", new File(picPath));
                picPathList.add(picPath);

                // 4、提取图片
                PDPage page = document.getPage(p - 1);
                PDResources res = page.getResources();
                Iterable<COSName> xit = res.getXObjectNames();
                for (COSName cosName : xit) {
                    //System.out.println(cosName.getName());
                    //判断是否图片资源，这个提取图片也很彻底，包括页眉页脚的图片也会被获取到
                    if (res.isImageXObject(cosName)) {
                        PDImageXObject pdImageXObject = (PDImageXObject) res.getXObject(cosName);
                        BufferedImage bImage = pdImageXObject.getImage(); //获取图片
                        String pngPath = "." + File.separator + fileDocument.getMd5() + "_" + p + "_" + cosName.getName() + ".png";
                        // 保存图片到本地
                        File pngFile = new File(pngPath);
                        ImageIO.write(bImage, "PNG", Files.newOutputStream(pngFile.toPath()));
                        pngPathList.add(pngPath);
                    }
                }
            }
        } catch (Exception e) {
            log.error("解析pdf文本文件出错", e);
            throw new RuntimeException(e); //TODO 换成自己的异常
        }

        // 5、识别文档是英文还是中文
        boolean isEnglish = containsChinese(detectLang.toString());
        System.out.println("containsChinese = " + isEnglish);

        map.put("txtFilePathList", textPathList);
        map.put("thumbPageFilePathList", picPathList);
        map.put("isEnglish", !isEnglish);
        map.put("pngFilePathList", pngPathList);
        return map;
    }


    public static void main(String[] args) {
        //测试
        String filePath = "D:\\Users\\Lenovo\\1.pdf";
        String textPath = "D:\\Users\\Lenovo\\1.txt";

    }



}
